package message

import "fmt"

type ID = uint16

type IMessage interface {
	MessageID() ID
	MessageName() string
	ResponseMessageID() ID
	RequestMessageID() ID
	Recycle()
}

type Factory[M IMessage] struct {
	ID       ID
	Name     string
	Producer func() M
}

func Register[M IMessage, Mgr ~map[ID]*Factory[M]](manager Mgr, iMsg M, producer func() M) error {
	if producer == nil {
		return fmt.Errorf("need producer")
	}

	id := iMsg.MessageID()
	name := iMsg.MessageName()

	if f, ok := manager[id]; ok {
		return fmt.Errorf("[%s][%d] duplicate message id, conflict message is [%s]", name, id, f.Name)
	}

	manager[id] = &Factory[M]{
		ID:       id,
		Name:     name,
		Producer: producer,
	}

	return nil
}

func MustRegister[M IMessage, Mgr ~map[ID]*Factory[M]](manager Mgr, iMsg M, producer func() M) {
	if err := Register[M, Mgr](manager, iMsg, producer); err != nil {
		panic(err)
	}
}
